package co.edu.uniandes.ecos.itera.tsp.mundo;

import com.sun.source.tree.AnnotationTree;
import com.sun.source.tree.ExpressionTree;
import com.sun.source.tree.Tree;
import com.sun.source.tree.Tree.Kind;
import com.sun.source.util.TreeScanner;

import co.edu.uniandes.ecos.itera.tsp.anotaciones.Loc;
import co.edu.uniandes.ecos.itera.tsp.anotaciones.LogT;

import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
import com.sun.source.util.JavacTask;
import com.sun.source.tree.CompilationUnitTree;

/**
 * Se encarga de analizar anotaciones de metodos y clases
 */
public class Analizador extends TreeScanner<Void, Void>
{
	/**
	 * Referencia que se usa para callbaks de metodos al procesar cada anotacion
	 */
	private DelegadoNegocio referenciaADelegadoNegocio;
	
	/**
	 * Constructor por defecto
	 * @param referencia Referencia para los callbacks
	 */
	public Analizador(DelegadoNegocio referencia)
	{
		this.referenciaADelegadoNegocio = referencia;
	}
	
	@Loc(size=19, taskId=72)
	@LogT(date="2011-02-19", min=5, taskId=8)
	/**
	 * Analiza un archivo en especial y establece los valores
	 * que vaya encontrando en las anotaciones analizadas
	 */
	public void analizarArchivo(String archivo)
	{
		try
		{
			JavaCompiler compilador = ToolProvider.getSystemJavaCompiler();
			StandardJavaFileManager manejadorArchivo = compilador.getStandardFileManager(null, null, null);
			Iterable<? extends JavaFileObject> unidadesDeCompilacion = manejadorArchivo.getJavaFileObjects(archivo);
			JavacTask tarea = (JavacTask)compilador.getTask(null, manejadorArchivo, null, null, null, unidadesDeCompilacion);
			Iterable<? extends CompilationUnitTree> arbolCargado = tarea.parse();
	
			for (CompilationUnitTree unidadDeCompilacion : arbolCargado) 
			{
				for(Tree td : unidadDeCompilacion.getTypeDecls()) 
				{
					td.accept(new Analizador(this.referenciaADelegadoNegocio), null);
				}
			}
		}
		catch(Exception ex)
		{
			System.out.println(ex.getMessage());
		}
	}
	
	@Override
	@Loc(size=75, taskId=72)
	@LogT(date="2011-03-19", min=135, taskId=72)
	public Void visitAnnotation(AnnotationTree arg0, Void arg1)
	{
		String nombreAnotacion = arg0.getAnnotationType().toString();
		
		int tmpId = 0;
		int tmpId2 = 0;
		int tmpMins = 0;
		int tmpSize = 0;
		String tmpFecha = "";
		String tmpString = "";
		Etapa tmpEtapa = Etapa.PLANEACION;
		boolean etapaEncontrada = false;
		
		for(ExpressionTree et: arg0.getArguments())
		{
			if(et.getKind().compareTo(Kind.ASSIGNMENT) == 0)
			{
				String[] t = et.toString().split("=");
				String parametro = t[0].trim().replace("\"", "");
				String valor = t[1].trim().replace("\"", "").replace("'", "");
				
				try
				{
					if(nombreAnotacion.compareTo("Loc") == 0) // Analisis de la anotacion Loc
					{
						if(parametro.compareTo("size") == 0)
							tmpSize = Integer.parseInt(valor);
						else if(parametro.compareTo("taskId") == 0)
							tmpId = Integer.parseInt(valor);
						
						if(tmpId > 0 && tmpSize > 0)
							this.referenciaADelegadoNegocio.adicionarLOCsATarea(tmpSize, tmpId);
					}
					else if(nombreAnotacion.compareTo("LogT") == 0)  // Analisis de la anotacion LogT
					{
						if(parametro.compareTo("taskId") == 0)
							tmpId = Integer.parseInt(valor);
						else if(parametro.compareTo("min") == 0)
							tmpMins = Integer.parseInt(valor);
						else if(parametro.compareTo("date") == 0)
							tmpFecha = valor;
						
						if(tmpId > 0 && tmpMins > 0 && tmpFecha.length() > 5)
							this.referenciaADelegadoNegocio.adicionarTiempoATarea(tmpMins, tmpId, tmpFecha);
					}
					else if(nombreAnotacion.compareTo("LogInt") == 0)  // Analisis de la anotacion LogInt
					{
						if(parametro.compareTo("intId") == 0)
							tmpId = Integer.parseInt(valor);
						else if(parametro.compareTo("min") == 0)
							tmpMins = Integer.parseInt(valor);
						else if(parametro.compareTo("date") == 0)
							tmpFecha = valor;
						else if(parametro.compareTo("taskId") == 0)
							tmpId2 = Integer.parseInt(valor);
						
						if(tmpId > 0 && tmpMins > 0 && tmpFecha.length() > 5 && tmpId2 > 0)
							this.referenciaADelegadoNegocio.adicionarInterrupcionATarea(tmpId, tmpId2, tmpMins, tmpFecha);
					}
					else if(nombreAnotacion.compareTo("LogD") == 0)  // Analisis de la anotacion LogD
					{
						if(parametro.compareTo("idDefecto") == 0)
							tmpId = Integer.parseInt(valor);
						else if(parametro.compareTo("taskId") == 0)
							tmpId2 = Integer.parseInt(valor);
						else if(parametro.compareTo("etapaInyectada") == 0)
						{
							for(Etapa etapa: Etapa.values())
							{
								String tmp = "Etapa." + etapa.toString();
								if(tmp.compareTo(valor) == 0)
								{
									tmpEtapa = etapa;
									etapaEncontrada = true;
									break;
								}
							}
						}
						
						if(tmpId > 0 && tmpId2 > 0 && etapaEncontrada)
							this.referenciaADelegadoNegocio.adicionarDefectoATarea(tmpEtapa, tmpId, tmpId2);
					}
					else if(nombreAnotacion.compareTo("Avance") == 0)  // Analisis de la anotacion Avance 
					{
						if(parametro.compareTo("termino") == 0)
							tmpString = valor;
						else if(parametro.compareTo("taskId") == 0)
							tmpId = Integer.parseInt(valor);
						
						if(tmpId > 0 && tmpString.trim().toUpperCase().compareTo("S") == 0)
							this.referenciaADelegadoNegocio.terminarTarea(tmpId);
					}
				}
				catch(Exception ex)
				{
					this.referenciaADelegadoNegocio.agregarErrorDeCarga(ex.getMessage());
				}
			}
		}
		
		return super.visitAnnotation(arg0, arg1);
	}
	
}
